const {
    Command
} = require('./command');

// 初始步骤
const DefaultCurrent = -1;
// 默认历史记录最大长度
const DefaultMaxStackLength = 100;

/**
 * 历史记录类（管理撤销、返回的栈）
 */
class History {

    static className() {
        return 'History';
    }

    /**
     * 构造方法
     */
    constructor() {
        this._stack = [];
        this.current = DefaultCurrent;
        this.maxStackLength = DefaultMaxStackLength;
        this._isSaved = true;
    }

    get isSaved() {
        return this._isSaved;
    }

    set isSaved(value) {
        this._isSaved = value;
    }

    /**
     * 是否可返回
     * @returns {boolean}
     */
    canRedo() {
        return this.stackLength > this.current;
    }

    /**
     * 是否可撤销
     * @returns {boolean}
     */
    canUndo() {
        return this.stackLength > 0 && this.current > DefaultCurrent;
    }

    get maxStackLength() {
        return this._maxStackLength;
    }

    set maxStackLength(value) {
        this._maxStackLength = value;
    }

    /**
     * 添加指令
     * @param command
     */
    pushCommand(command) {
        if (this.stackLength > this.current + 1) {
            this.stack.splice(this.current + 1, this.stackLength - this.current);
        }
        this.stack.push(command);
        this.current++;
        if (this.maxStackLength < this.stackLength) {
            this.stack.shift();
            this.current = this.maxStackLength - 1;
        }
    }

    /**
     * 执行指令
     * @param command
     */
    applyCommand(command) {
        this.onApply && this.onApply(command);
        this.isSaved = false;
    }

    /**
     * 添加指令的同时执行指令
     * @param command
     */
    pushCommandAndApply(command) {
        this.pushCommand(command);
        this.applyCommand(command);
    }

    /**
     * 栈的长度（步骤长度）
     * @returns {*}
     */
    get stackLength() {
        return this.stack.length;
    }

    /**
     * 存储指令的栈（数组）
     * @returns {Array<Command>}
     */
    get stack() {
        return this._stack;
    }

    /**
     * @param value {Array<Command>}
     */
    set stack(value) {
        this._stack = value;
    }

    /**
     * 返回
     */
    redo() {
        let command = null;
        if (this.canRedo()) {
            this.current++;
            if (this.current < this.stackLength) {
                command = this.stack[this.current];
                this.onApply && this.onApply(command);
            }
            this.current = Math.min(this.current, this.stackLength - 1);
        }
        return command;
    }

    /**
     * 撤销
     */
    undo() {
        let command = null;
        if (this.canUndo()) {
            if (this.current > DefaultCurrent) {
                command = this.stack[this.current];
                this.onUnapply && this.onUnapply(command);
            }
            this.current--;
            this.current = Math.max(this.current, DefaultCurrent);
        }
        return command;
    }

    get onApply() {
        return this._onApply;
    }

    set onApply(value) {
        this._onApply = value;
    }

    get onUnapply() {
        return this._onUnapply;
    }

    set onUnapply(value) {
        this._onUnapply = value;
    }
}

History.Events = {
    Apply: 'apply',
    Unapply: 'unapply',
};

module.exports = {
    History
};
